(function (w) {

  // 深拷贝
  function deepClone(obj) {
    if (typeof obj !== 'object' || obj == null) {
      return obj
    }
    let res = obj instanceof Array ? [] : {}
    for (k in obj) {
      if (obj.hasOwnProperty(k)) {
        res[k] = deepClone(obj[k])
      }
    }
    return res
  }

  // 初始化模块
  function initModule(module) {
    if (module.isInitFun) {
      try {
        module.callBack = module.callBack()
      } catch (err) {
        module.callBack = null
        const errStr = err.toString()
        if (errStr.includes('Error: Error: Error:') || errStr.includes('RangeError: Maximum call stack size exceeded')) {
          throw new Error(`引入${module.name}模块失败,模块间不可互相引入，或者模块引入自己,否则会爆栈`)
        } else {
          throw new Error(err)
        }
      }

      if (module.result.exports && !module.name) {
        module.result.exports = null
        throw new Error('module 命名为空，无法返回内容')
      }
      module.isInitFun = false
    }
    return module
  }

  module = (() => {

    let modules = []

    function require(name) {
      let module = modules.find(item => (item.name != undefined && item.name == name))
      if (!module) {
        throw new Error(`引入的模块:${name}不存在`)
      }

      module = module.isInitFun ? initModule(module) : module

      if ((module.result.exports === undefined || module.result.exports === null)) {
        throw new Error(`模块：${module.name}引入失败,内容为空`);
      }

      return deepClone(module.result.exports)
    }

    function define(name = undefined, fn) {
      if (name instanceof Function && fn == undefined) {
        fn = name
        name = undefined
      }

      if (name && typeof name !== 'string') {
        throw new Error('module 命名只能以字符串命名')
      }

      modules.forEach(item => {
        if (item.name === name && name != undefined) {
          throw new Error('module命名重复: ' + name + ' 已被声明')
        }
      })

      let module = {
        name,
        callBack: function () {
          const res = fn.call(null, this.result)
          if (res) this.result.exports = res
        },
        result: { exports: null },
        isInitFun: true
      }

      modules.push(module)
    }

    Promise.resolve().then(() => {
      modules.forEach(module => initModule(module))
      modules = modules.filter(module => (module.name != undefined && module.result.exports != undefined))
      console.log('有返回值的模块如下:');
      console.dir(modules);
    })
    return {
      define,
      require
    }
  })()

  w.define = module.define
  w.require = module.require
})(window)


define('addition', function (result) {
  const originalValue = 1
  function add(value) {
    return originalValue + value
  }
  result.exports = add
  // return add
})


define('addTwo', function (result) {
  const add = require('addition')
  return function (value) {
    return add(2) + value
  }
})

define(function () {
  const add = require('addTwo')
  console.log(add(3))
})



